package com.xy.xyaicpzs.controller;

import com.xy.xyaicpzs.common.ErrorCode;
import com.xy.xyaicpzs.common.ResultUtils;
import com.xy.xyaicpzs.common.response.ApiResponse;
import com.xy.xyaicpzs.common.response.PageResponse;
import com.xy.xyaicpzs.domain.entity.LotteryDraws;
import com.xy.xyaicpzs.domain.entity.PredictRecord;
import com.xy.xyaicpzs.domain.entity.User;
import com.xy.xyaicpzs.domain.entity.HistoryAll;
import com.xy.xyaicpzs.domain.entity.History100;
import com.xy.xyaicpzs.domain.entity.HistoryTop;
import com.xy.xyaicpzs.domain.entity.HistoryTop100;
import com.xy.xyaicpzs.domain.entity.BlueHistoryAll;
import com.xy.xyaicpzs.domain.entity.BlueHistory100;
import com.xy.xyaicpzs.domain.entity.BlueHistoryTop;
import com.xy.xyaicpzs.domain.entity.BlueHistoryTop100;
import com.xy.xyaicpzs.domain.entity.T7;
import com.xy.xyaicpzs.domain.entity.T8;
import com.xy.xyaicpzs.domain.entity.T11;
import com.xy.xyaicpzs.domain.entity.T3;
import com.xy.xyaicpzs.domain.entity.T4;
import com.xy.xyaicpzs.domain.entity.T5;
import com.xy.xyaicpzs.domain.entity.T6;
import com.xy.xyaicpzs.service.BallAnalysisService;
import com.xy.xyaicpzs.service.LotteryDrawsService;
import com.xy.xyaicpzs.service.PredictRecordService;
import com.xy.xyaicpzs.service.UserService;
import com.xy.xyaicpzs.service.HistoryAllService;
import com.xy.xyaicpzs.service.History100Service;
import com.xy.xyaicpzs.service.HistoryTopService;
import com.xy.xyaicpzs.service.HistoryTop100Service;
import com.xy.xyaicpzs.service.BlueHistoryAllService;
import com.xy.xyaicpzs.service.BlueHistory100Service;
import com.xy.xyaicpzs.service.BlueHistoryTopService;
import com.xy.xyaicpzs.service.BlueHistoryTop100Service;
import com.xy.xyaicpzs.service.T7Service;
import com.xy.xyaicpzs.service.T8Service;
import com.xy.xyaicpzs.service.T11Service;
import com.xy.xyaicpzs.service.T3Service;
import com.xy.xyaicpzs.service.T4Service;
import com.xy.xyaicpzs.service.T5Service;
import com.xy.xyaicpzs.service.T6Service;
import com.xy.xyaicpzs.domain.vo.BallHitRateVO;
import com.xy.xyaicpzs.domain.vo.PrizeEstimateVO;
import com.xy.xyaicpzs.domain.vo.BallCombinationAnalysisVO;
import com.xy.xyaicpzs.domain.vo.BallPersistenceAnalysisVO;
import com.xy.xyaicpzs.domain.vo.RedBallHitRateVO;
import com.xy.xyaicpzs.domain.vo.BallAnalysisResultVO;
import com.xy.xyaicpzs.domain.vo.FollowBallAnalysisResultVO;
import com.xy.xyaicpzs.domain.vo.BlueBallAnalysisResultVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Comparator;

/**
 * 球号分析控制器
 * 提供球号分析算法的API接口
 */
@Slf4j
@RestController
@RequestMapping("/ball-analysis")
@Tag(name = "球号分析", description = "球号分析算法API")
public class BallAnalysisController {

    @Autowired
    private BallAnalysisService ballAnalysisService;

    @Autowired
    private LotteryDrawsService lotteryDrawsService;

    @Autowired
    private PredictRecordService predictRecordService;

    @Autowired
    private UserService userService;

    @Autowired
    private HistoryAllService historyAllService;

    @Autowired
    private History100Service history100Service;

    @Autowired
    private HistoryTopService historyTopService;

    @Autowired
    private HistoryTop100Service historyTop100Service;

    @Autowired
    private BlueHistoryAllService blueHistoryAllService;

    @Autowired
    private BlueHistory100Service blueHistory100Service;

    @Autowired
    private BlueHistoryTopService blueHistoryTopService;

    @Autowired
    private BlueHistoryTop100Service blueHistoryTop100Service;

    @Autowired
    private T7Service t7Service;

    @Autowired
    private T8Service t8Service;

    @Autowired
    private T11Service t11Service;

    @Autowired
    private T3Service t3Service;

    @Autowired
    private T4Service t4Service;

    @Autowired
    private T5Service t5Service;

    @Autowired
    private T6Service t6Service;

    /**
     * 获取近期开奖信息
     * @param limit 获取条数，可选参数，默认15条
     * @return 近期开奖信息列表
     */
    @GetMapping("/recent-draws")
    @Operation(summary = "获取近期开奖信息", description = "获取最近的开奖信息，默认返回10条，按开奖期号倒序排列")
    public ApiResponse<List<LotteryDraws>> getRecentDraws(
            @Parameter(description = "获取条数，默认10条", required = false)
            @RequestParam(required = false, defaultValue = "10") Integer limit, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        try {
            log.info("接收到获取近期开奖信息请求：条数={}", limit);
            
            // 调用服务获取近期开奖信息
            List<LotteryDraws> result = lotteryDrawsService.getRecentDraws(limit);
            
            log.info("获取近期开奖信息完成，返回{}条记录", result.size());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取近期开奖信息失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取近期开奖信息失败：" + e.getMessage());
        }
    }

    /**
     * 获取最新100条开奖信息
     * @return 最新100条开奖信息列表
     */
    @GetMapping("/recent-100-draws")
    @Operation(summary = "获取最新100条开奖信息", description = "获取lottery_draws表中最新的100条开奖信息，按开奖期号倒序排列")
    public ApiResponse<List<LotteryDraws>> getRecent100Draws(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到获取最新100条开奖信息请求");
            
            // 调用服务获取最新100条开奖信息
            List<LotteryDraws> result = lotteryDrawsService.getRecentDraws(100);
            
            log.info("获取最新100条开奖信息完成，返回{}条记录", result.size());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取最新100条开奖信息失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取最新100条开奖信息失败：" + e.getMessage());
        }
    }

    /**
     * 根据日期范围查询开奖信息
     * @param startDate 开始日期（可选，格式：yyyy-MM-dd）
     * @param endDate 结束日期（可选，格式：yyyy-MM-dd）
     * @return 开奖信息列表
     */
    @GetMapping("/query-draws")
    @Operation(summary = "按日期范围查询开奖信息", description = "根据日期范围查询开奖信息，支持单边日期查询")
    public ApiResponse<List<LotteryDraws>> queryDraws(
            @Parameter(description = "开始日期，格式：yyyy-MM-dd，例如：2025-01-01", required = false)
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
            
            @Parameter(description = "结束日期，格式：yyyy-MM-dd，例如：2025-01-31", required = false)
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate,
            HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        
        try {
            log.info("接收到按日期范围查询开奖信息请求：开始日期={}，结束日期={}", startDate, endDate);
            
            // 日期范围验证
            if (startDate != null && endDate != null && startDate.after(endDate)) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "开始日期不能晚于结束日期");
            }
            
            // 调用服务按日期范围查询开奖信息
            List<LotteryDraws> result = lotteryDrawsService.getByDateRange(startDate, endDate);
            
            log.info("按日期范围查询开奖信息完成，返回{}条记录", result.size());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("按日期范围查询开奖信息失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "查询开奖信息失败：" + e.getMessage());
        }
    }

    /**
     * 根据期号精准查询单条开奖信息
     * @param drawId 开奖期号
     * @return 开奖信息
     */
    @GetMapping("/draw/{drawId}")
    @Operation(summary = "根据期号查询开奖信息", description = "根据期号精准查询单条开奖信息")
    public ApiResponse<LotteryDraws> getDrawById(
            @Parameter(description = "开奖期号，例如：2025056", required = true)
            @PathVariable Long drawId,
            HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        
        try {
            log.info("接收到根据期号查询开奖信息请求：期号={}", drawId);
            
            // 调用服务查询开奖信息
            LotteryDraws result = lotteryDrawsService.getByDrawId(drawId);
            
            if (result == null) {
                log.warn("未找到期号为{}的开奖信息", drawId);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, "未找到期号为" + drawId + "的开奖信息");
            }
            
            log.info("根据期号查询开奖信息完成：{}", result.getDrawId());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("根据期号查询开奖信息失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "查询开奖信息失败：" + e.getMessage());
        }
    }

    /**
     * 根据开奖期号查询开奖球号
     * @param drawId 开奖期号
     * @return 7个中奖球号
     */
    @GetMapping("/draw/{drawId}/numbers")
    @Operation(summary = "根据开奖期号查询开奖球号", description = "根据开奖期号查询7个中奖球号（6个红球+1个蓝球）")
    public ApiResponse<List<Integer>> getDrawNumbersById(
            @Parameter(description = "开奖期号，例如：2025056", required = true)
            @PathVariable Long drawId,
            HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }

        try {
            log.info("接收到根据期号查询开奖球号请求：期号={}", drawId);

            // 调用服务查询开奖信息
            LotteryDraws result = lotteryDrawsService.getByDrawId(drawId);

            if (result == null) {
                log.warn("未找到期号为{}的开奖信息", drawId);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, "未找到期号为" + drawId + "的开奖信息");
            }

            List<Integer> winningNumbers = new java.util.ArrayList<>();
            winningNumbers.add(result.getRedBall1());
            winningNumbers.add(result.getRedBall2());
            winningNumbers.add(result.getRedBall3());
            winningNumbers.add(result.getRedBall4());
            winningNumbers.add(result.getRedBall5());
            winningNumbers.add(result.getRedBall6());
            winningNumbers.add(result.getBlueBall());

            log.info("根据期号查询开奖球号完成：{}，球号：{}", drawId, winningNumbers);
            return ResultUtils.success(winningNumbers);

        } catch (Exception e) {
            log.error("根据期号查询开奖球号失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "查询开奖球号失败：" + e.getMessage());
        }
    }

    /**
     * 创建预测记录
     * @param userId 用户ID
     * @param drawId 开奖期号
     * @param drawDate 开奖日期
     * @param redBalls 6个红球号码，用逗号分隔
     * @param blueBall 蓝球号码
     * @return 创建的预测记录
     */
    @PostMapping("/create-predict")
    @Operation(summary = "创建预测记录", description = "向predict_record表插入一条预测记录数据")
    public ApiResponse<PredictRecord> createPredictRecord(
            @Parameter(description = "用户ID，例如：1001", required = true)
            @RequestParam Long userId,
            
            @Parameter(description = "开奖期号，例如：2025056", required = true)
            @RequestParam Long drawId,
            
            @Parameter(description = "开奖日期，格式：yyyy-MM-dd", required = false)
            @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date drawDate,
            
            @Parameter(description = "6个红球号码，用逗号分隔，例如：1,5,12,18,25,33", required = true)
            @RequestParam String redBalls,
            
            @Parameter(description = "蓝球号码，例如：8", required = true)
            @RequestParam Integer blueBall) {
        
        try {
            log.info("接收到创建预测记录请求：用户ID={}，期号={}，开奖日期={}，红球={}，蓝球={}", 
                    userId, drawId, drawDate, redBalls, blueBall);
            
            // 解析红球号码
            List<Integer> redBallList = parseRedBalls(redBalls, 6, "红球");
            
            // 调用服务创建预测记录
            PredictRecord result = predictRecordService.createPredictRecord(userId, drawId, drawDate, redBallList, blueBall);
            
            log.info("创建预测记录完成，用户ID：{}，记录ID：{}", userId, result.getId());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("创建预测记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "创建预测记录失败：" + e.getMessage());
        }
    }

    /**
     * 根据用户ID获取预测记录
     * @param userId 用户ID
     * @return 用户的所有预测记录列表
     */
    @GetMapping("/predict-records/{userId}")
    @Operation(summary = "获取用户预测记录", description = "根据用户ID分页获取该用户的预测记录，按预测时间倒序排列，每页5条")
    public ApiResponse<PageResponse<PredictRecord>> getPredictRecordsByUserId(
            @Parameter(description = "用户ID，例如：1001", required = true)
            @PathVariable Long userId,
            @Parameter(description = "页码，从1开始，默认为1", required = false)
            @RequestParam(value = "page", defaultValue = "1") Integer page,
            HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "用户未登录");
        }

        try {
            log.info("接收到获取用户预测记录请求：用户ID={}，页码={}", userId, page);
            
            // 参数校验
            if (page < 1) {
                page = 1;
            }
            
            // 获取总记录数
            Long total = predictRecordService.getPredictRecordsCountByUserId(userId);
            
            // 调用服务获取用户预测记录（分页，每页5条）
            List<PredictRecord> records = predictRecordService.getPredictRecordsByUserIdWithPaging(userId, page, 5);
            
            // 创建分页响应对象
            PageResponse<PredictRecord> pageResponse = PageResponse.of(records, total, page, 5);
            
            log.info("获取用户预测记录完成，用户ID：{}，页码：{}，返回{}条记录，总记录数：{}", userId, page, records.size(), total);
            return ResultUtils.success(pageResponse);
            
        } catch (Exception e) {
            log.error("获取用户预测记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取用户预测记录失败：" + e.getMessage());
        }
    }

    /**
     * 球号分析算法
     * @param userId 用户ID
     * @param level 高位/中位/低位标识 (H/M/L)
     * @param redBalls 6个红球号码，用逗号分隔
     * @param blueBall 蓝球号码
     * @return 分析结果：出现频率最高的前11位数字
     */
    @PostMapping("/analyze")
    @Operation(summary = "首球算法", description = "根据输入的级别、红球和蓝球，分析出现频率最高的前11位数字及筛选过程说明")
    public ApiResponse<BallAnalysisResultVO> analyzeBalls(
            @Parameter(description = "用户ID，例如：1001", required = true)
            @RequestParam Long userId,
            
            @Parameter(description = "级别：H(高位)/M(中位)/L(低位)", required = true)
            @RequestParam String level,
            
            @Parameter(description = "6个红球号码，用逗号分隔，例如：1,5,12,18,25,33", required = true)
            @RequestParam String redBalls,
            
            @Parameter(description = "蓝球号码，例如：8", required = true)
            @RequestParam Integer blueBall) {
        
        try {
            log.info("接收到球号分析请求：用户ID={}，级别={}，红球={}，蓝球={}", userId, level, redBalls, blueBall);
            
            // 校验用户VIP有效期
            User user = userService.getById(userId);
            if (user == null) {
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
            }
            
            Date now = new Date();
            if (user.getVipExpire() == null || user.getVipExpire().before(now)) {
                return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
            }
            
            // 解析红球号码
            List<Integer> redBallList = parseRedBalls(redBalls, 6, "红球");
            
            // 调用分析服务（包含筛选过程说明）
            BallAnalysisResultVO result = ballAnalysisService.analyzeBallsWithProcess(level, redBallList, blueBall);
            
            log.info("球号分析完成，结果：{}，过程说明：{}", result.getResult(), result.getFilteringProcess());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("球号分析失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "球号分析失败：" + e.getMessage());
        }
    }

    /**
     * 跟随球号分析算法
     * @param userId 用户ID
     * @param level 高位/中位/低位标识 (H/M/L)
     * @param firstThreeRedBalls 前3个红球号码，用逗号分隔
     * @param lastSixRedBalls 后6个红球号码，用逗号分隔
     * @param blueBall 蓝球号码
     * @return 分析结果：出现频率最高的前8位数字及筛选过程说明
     */
    @PostMapping("/fallow")
    @Operation(summary = "跟随球号分析算法", description = "根据输入的级别、前3个红球、后6个红球和蓝球，分析出现频率最高的前8位数字及筛选过程说明")
    public ApiResponse<FollowBallAnalysisResultVO> fallowBallAnalysis(
            @Parameter(description = "用户ID，例如：1001", required = true)
            @RequestParam Long userId,
            
            @Parameter(description = "级别：H(高位)/M(中位)/L(低位)", required = true)
            @RequestParam String level,
            
            @Parameter(description = "前3个红球号码，用逗号分隔，例如：7,24,27", required = true)
            @RequestParam String firstThreeRedBalls,
            
            @Parameter(description = "后6个红球号码，用逗号分隔，例如：21,10,5,15,23,28", required = true)
            @RequestParam String lastSixRedBalls,
            
            @Parameter(description = "蓝球号码，例如：16", required = true)
            @RequestParam Integer blueBall) {
        
        try {
            log.info("接收到跟随球号分析请求：用户ID={}，级别={}，前3个红球={}，后6个红球={}，蓝球={}", 
                    userId, level, firstThreeRedBalls, lastSixRedBalls, blueBall);
            
            // 校验用户VIP有效期
            User user = userService.getById(userId);
            if (user == null) {
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
            }
            
            Date now = new Date();
            if (user.getVipExpire() == null || user.getVipExpire().before(now)) {
                return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
            }
            
            // 解析红球号码
            List<Integer> firstThreeRedBallList = parseRedBalls(firstThreeRedBalls, 3, "前3个红球");
            List<Integer> lastSixRedBallList = parseRedBalls(lastSixRedBalls, 6, "后6个红球");
            
            // 调用分析服务（包含筛选过程说明）
            FollowBallAnalysisResultVO result = ballAnalysisService.fallowBallAnalysisWithProcess(level, firstThreeRedBallList, lastSixRedBallList, blueBall);
            
            log.info("跟随球号分析完成，结果：{}，过程说明：{}", result.getResult(), result.getFilteringProcess());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("跟随球号分析失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "跟随球号分析失败：" + e.getMessage());
        }
    }

    /**
     * 解析红球号码字符串
     */
    private List<Integer> parseRedBalls(String redBalls, int expectedCount, String ballType) {
        if (redBalls == null || redBalls.trim().isEmpty()) {
            throw new IllegalArgumentException(ballType + "号码不能为空");
        }
        
        try {
            String[] parts = redBalls.split(",");
            if (parts.length != expectedCount) {
                throw new IllegalArgumentException(ballType + "数量必须为" + expectedCount + "个，实际：" + parts.length);
            }
            
            List<Integer> result = Arrays.stream(parts)
                    .map(String::trim)
                    .map(Integer::parseInt)
                    .collect(java.util.stream.Collectors.toList());
            
            // 验证红球号码范围
            for (Integer ball : result) {
                if (ball < 1 || ball > 33) {
                    throw new IllegalArgumentException(ballType + "号码必须在1-33范围内，错误值：" + ball);
                }
            }
            
            return result;
            
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException(ballType + "号码格式错误，请使用逗号分隔的数字");
        }
    }

    /**
     * 蓝球分析算法
     * @param userId 用户ID
     * @param level 高位/中位/低位标识 (H/M/L)
     * @param predictedRedBalls 6个预测红球号码，用逗号分隔
     * @param predictedBlueBalls 2个预测蓝球号码，用逗号分隔
     * @param lastRedBalls 6个上期红球号码，用逗号分隔
     * @param lastBlueBall 上期蓝球号码
     * @return 分析结果：频率最高的前4个蓝球号码及其筛选过程说明
     */
    @PostMapping("/blue-ball")
    @Operation(summary = "蓝球分析算法", description = "根据输入的级别、预测红球、预测蓝球、上期红球和上期蓝球，分析出频率最高的前4个蓝球号码，并返回详细的筛选过程说明")
    public ApiResponse<BlueBallAnalysisResultVO> blueBallAnalysis(
            @Parameter(description = "用户ID，例如：1001", required = true)
            @RequestParam Long userId,
            
            @Parameter(description = "级别：H(高位)/M(中位)/L(低位)", required = true)
            @RequestParam String level,
            
            @Parameter(description = "6个预测红球号码，用逗号分隔，例如：26,20,18,32,10,14", required = true)
            @RequestParam String predictedRedBalls,
            
            @Parameter(description = "2个预测蓝球号码，用逗号分隔，例如：5,8", required = true)
            @RequestParam String predictedBlueBalls,
            
            @Parameter(description = "6个上期红球号码，用逗号分隔，例如：7,24,27,21,10,5", required = true)
            @RequestParam String lastRedBalls,
            
            @Parameter(description = "上期蓝球号码，例如：16", required = true)
            @RequestParam Integer lastBlueBall) {
        
        try {
            log.info("接收到蓝球分析请求：用户ID={}，级别={}，预测红球={}，预测蓝球={}，上期红球={}，上期蓝球={}", 
                    userId, level, predictedRedBalls, predictedBlueBalls, lastRedBalls, lastBlueBall);
            
            // 校验用户VIP有效期
            User user = userService.getById(userId);
            if (user == null) {
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
            }
            
            Date now = new Date();
            if (user.getVipExpire() == null || user.getVipExpire().before(now)) {
                return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
            }
            
            // 解析球号
            List<Integer> predictedRedBallList = parseRedBalls(predictedRedBalls, 6, "预测红球");
            List<Integer> predictedBlueBallList = parseBlueBalls(predictedBlueBalls, 2, "预测蓝球");
            List<Integer> lastRedBallList = parseRedBalls(lastRedBalls, 6, "上期红球");
            
            // 调用分析服务（带过程说明）
            BlueBallAnalysisResultVO result = ballAnalysisService.blueBallAnalysisWithProcess(
                level, predictedRedBallList, predictedBlueBallList, lastRedBallList, lastBlueBall);
            
            log.info("蓝球分析完成，结果：{}，过程说明：{}", result.getResult(), result.getFilteringProcess());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("蓝球分析失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "蓝球分析失败：" + e.getMessage());
        }
    }

    /**
     * 解析蓝球号码字符串
     */
    private List<Integer> parseBlueBalls(String blueBalls, int expectedCount, String ballType) {
        if (blueBalls == null || blueBalls.trim().isEmpty()) {
            throw new IllegalArgumentException(ballType + "号码不能为空");
        }
        
        try {
            String[] parts = blueBalls.split(",");
            if (parts.length != expectedCount) {
                throw new IllegalArgumentException(ballType + "数量必须为" + expectedCount + "个，实际：" + parts.length);
            }
            
            List<Integer> result = Arrays.stream(parts)
                    .map(String::trim)
                    .map(Integer::parseInt)
                    .collect(java.util.stream.Collectors.toList());
            
            // 验证蓝球号码范围
            for (Integer ball : result) {
                if (ball < 1 || ball > 16) {
                    throw new IllegalArgumentException(ballType + "号码必须在1-16范围内，错误值：" + ball);
                }
            }
            
            return result;
            
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException(ballType + "号码格式错误，请使用逗号分隔的数字");
        }
    }

    /**
     * 获取红球历史数据全部记录
     * @return 历史数据全部记录列表
     */
    @GetMapping("/history-all")
    @Operation(summary = "获取历史数据全部记录", description = "获取history_all表中的所有历史数据记录")
    public ApiResponse<List<HistoryAll>> getHistoryAll(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到获取历史数据全部记录请求");
            
            // 调用服务获取全部历史数据
            List<HistoryAll> result = historyAllService.list();
            
            log.info("获取历史数据全部记录完成，返回{}条记录", result.size());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取历史数据全部记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取历史数据全部记录失败：" + e.getMessage());
        }
    }

    /**
     * 获取红球最近100期数据记录
     * @return 最近100期数据记录列表
     */
    @GetMapping("/history-100")
    @Operation(summary = "获取最近100期数据记录", description = "获取history_100表中的所有最近100期数据记录")
    public ApiResponse<List<History100>> getHistory100(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到获取最近100期数据记录请求");
            
            // 调用服务获取最近100期数据
            List<History100> result = history100Service.list();
            
            log.info("获取最近100期数据记录完成，返回{}条记录", result.size());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取最近100期数据记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取最近100期数据记录失败：" + e.getMessage());
        }
    }

    /**
     * 获取红球历史数据排行记录
     * @return 历史数据排行记录列表
     */
    @GetMapping("/history-top")
    @Operation(summary = "获取历史数据排行记录", description = "获取history_top表中的所有历史数据排行记录")
    public ApiResponse<List<HistoryTop>> getHistoryTop(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到获取历史数据排行记录请求");
            
            // 调用服务获取历史数据排行
            List<HistoryTop> result = historyTopService.list();
            
            log.info("获取历史数据排行记录完成，返回{}条记录", result.size());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取历史数据排行记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取历史数据排行记录失败：" + e.getMessage());
        }
    }

    /**
     * 获取红球100期数据排行记录
     * @return 100期数据排行记录列表
     */
    @GetMapping("/history-top-100")
    @Operation(summary = "获取红球100期数据排行记录", description = "获取history_top_100表中的所有100期数据排行记录")
    public ApiResponse<List<HistoryTop100>> getHistoryTop100(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到获取100期数据排行记录请求");
            
            // 调用服务获取100期数据排行
            List<HistoryTop100> result = historyTop100Service.list();
            
            log.info("获取100期数据排行记录完成，返回{}条记录", result.size());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取100期数据排行记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取100期数据排行记录失败：" + e.getMessage());
        }
    }

    /**
     * 获取蓝球历史数据全部记录
     * @return 蓝球历史数据全部记录列表
     */
    @GetMapping("/blue-history-all")
    @Operation(summary = "获取蓝球历史数据全部记录", description = "获取blue_history_all表中的所有蓝球历史数据记录")
    public ApiResponse<List<BlueHistoryAll>> getBlueHistoryAll(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到获取蓝球历史数据全部记录请求");
            
            // 调用服务获取蓝球全部历史数据
            List<BlueHistoryAll> result = blueHistoryAllService.list();
            
            log.info("获取蓝球历史数据全部记录完成，返回{}条记录", result.size());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取蓝球历史数据全部记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取蓝球历史数据全部记录失败：" + e.getMessage());
        }
    }

    /**
     * 获取蓝球最近100期数据记录
     * @return 蓝球最近100期数据记录列表
     */
    @GetMapping("/blue-history-100")
    @Operation(summary = "获取蓝球最近100期数据记录", description = "获取blue_history_100表中的所有蓝球最近100期数据记录")
    public ApiResponse<List<BlueHistory100>> getBlueHistory100(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到获取蓝球最近100期数据记录请求");
            
            // 调用服务获取蓝球最近100期数据
            List<BlueHistory100> result = blueHistory100Service.list();
            
            log.info("获取蓝球最近100期数据记录完成，返回{}条记录", result.size());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取蓝球最近100期数据记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取蓝球最近100期数据记录失败：" + e.getMessage());
        }
    }

    /**
     * 获取蓝球历史数据排行记录
     * @return 蓝球历史数据排行记录列表
     */
    @GetMapping("/blue-history-top")
    @Operation(summary = "获取蓝球历史数据排行记录", description = "获取blue_history_top表中的所有蓝球历史数据排行记录")
    public ApiResponse<List<BlueHistoryTop>> getBlueHistoryTop(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到获取蓝球历史数据排行记录请求");
            
            // 调用服务获取蓝球历史数据排行
            List<BlueHistoryTop> result = blueHistoryTopService.list();
            
            log.info("获取蓝球历史数据排行记录完成，返回{}条记录", result.size());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取蓝球历史数据排行记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取蓝球历史数据排行记录失败：" + e.getMessage());
        }
    }

    /**
     * 获取蓝球100期数据排行记录
     * @return 蓝球100期数据排行记录列表
     */
    @GetMapping("/blue-history-top-100")
    @Operation(summary = "获取蓝球100期数据排行记录", description = "获取blue_history_top_100表中的所有蓝球100期数据排行记录")
    public ApiResponse<List<BlueHistoryTop100>> getBlueHistoryTop100(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到获取蓝球100期数据排行记录请求");
            
            // 调用服务获取蓝球100期数据排行
            List<BlueHistoryTop100> result = blueHistoryTop100Service.list();
            
            log.info("获取蓝球100期数据排行记录完成，返回{}条记录", result.size());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取蓝球100期数据排行记录失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取蓝球100期数据排行记录失败：" + e.getMessage());
        }
    }

    /**
     * 红球与红球的组合性分析
     * @param masterBall 主球号码（第一个红球）
     * @param slaveBall 随球号码（第二个红球）
     * @return 面系数分析结果
     */
    @GetMapping("/red-ball-combination-analysis")
    @Operation(summary = "红球与红球的组合性分析", description = "根据主球和随球号码，查询t7表获取面系数，并计算主球与其他球号的组合情况")
    public ApiResponse<BallCombinationAnalysisVO> redBallCombinationAnalysis(
            @Parameter(description = "主球号码，例如：5", required = true)
            @RequestParam Integer masterBall,
            
            @Parameter(description = "随球号码，例如：12", required = true)
            @RequestParam Integer slaveBall,
            
            HttpServletRequest request) {
        
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到红球与红球的组合性分析请求：主球={}，随球={}", masterBall, slaveBall);
            
            // 参数校验
            if (masterBall == null || slaveBall == null) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "主球和随球号码不能为空");
            }
            
            // 验证红球号码范围
            if (masterBall < 1 || masterBall > 33) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "主球号码必须在1-33范围内，错误值：" + masterBall);
            }
            
            if (slaveBall < 1 || slaveBall > 33) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "随球号码必须在1-33范围内，错误值：" + slaveBall);
            }
            
            // 查询当前两个球的面系数
            T7 t7Record = t7Service.lambdaQuery()
                    .eq(T7::getMasterBallNumber, masterBall)
                    .eq(T7::getSlaveBallNumber, slaveBall)
                    .one();
            
            if (t7Record == null) {
                log.warn("未找到主球{}和随球{}的组合记录", masterBall, slaveBall);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, 
                        String.format("未找到主球%d和随球%d的组合记录", masterBall, slaveBall));
            }
            
            Double faceCoefficient = t7Record.getFaceCoefficient();
            
            // 查询主球与所有其他球的组合系数
            List<T7> allCombinations = t7Service.lambdaQuery()
                    .eq(T7::getMasterBallNumber, masterBall)
                    .ne(T7::getSlaveBallNumber, masterBall)  // 排除自身
                    .list();
            
            if (allCombinations.isEmpty()) {
                log.warn("未找到主球{}的组合记录", masterBall);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, 
                        String.format("未找到主球%d的组合记录", masterBall));
            }
            
            // 找出系数最高的球号
            T7 highest = allCombinations.stream()
                    .max(Comparator.comparing(T7::getFaceCoefficient))
                    .orElse(null);
            
            // 找出系数最低的球号
            T7 lowest = allCombinations.stream()
                    .min(Comparator.comparing(T7::getFaceCoefficient))
                    .orElse(null);
            
            // 计算平均系数
            double avgCoefficient = allCombinations.stream()
                    .mapToDouble(T7::getFaceCoefficient)
                    .average()
                    .orElse(0.0);
            
            // 获取最新的一期开奖期号
            Long latestDrawId = lotteryDrawsService.lambdaQuery()
                    .orderByDesc(LotteryDraws::getDrawId)
                    .last("LIMIT 1")
                    .oneOpt()
                    .map(LotteryDraws::getDrawId)
                    .orElse(null);
                    
            // 构建返回结果
            BallCombinationAnalysisVO result = BallCombinationAnalysisVO.builder()
                    .faceCoefficient(faceCoefficient)
                    .highestBall(highest != null ? highest.getSlaveBallNumber() : null)
                    .highestCoefficient(highest != null ? highest.getFaceCoefficient() : null)
                    .lowestBall(lowest != null ? lowest.getSlaveBallNumber() : null)
                    .lowestCoefficient(lowest != null ? lowest.getFaceCoefficient() : null)
                    .averageCoefficient(avgCoefficient)
                    .latestDrawId(latestDrawId)
                    .build();
            
            log.info("红球与红球的组合性分析完成：{}", result);
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("红球与红球的组合性分析失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "红球与红球的组合性分析失败：" + e.getMessage());
        }
    }

    /**
     * 红球与蓝球的组合性分析
     * @param masterBall 主球号码（红球）
     * @param slaveBall 随球号码（蓝球）
     * @return 面系数分析结果
     */
    @GetMapping("/red-blue-combination-analysis")
    @Operation(summary = "红球与蓝球的组合性分析", description = "根据红球主球和蓝球随球号码，查询t8表获取面系数，并返回扩展分析")
    public ApiResponse<BallCombinationAnalysisVO> redBlueCombinationAnalysis(
            @Parameter(description = "主球号码（红球），例如：5", required = true)
            @RequestParam Integer masterBall,
            
            @Parameter(description = "随球号码（蓝球），例如：8", required = true)
            @RequestParam Integer slaveBall,
            
            HttpServletRequest request) {
        
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到红球与蓝球的组合性分析请求：主球（红球）={}，随球（蓝球）={}", masterBall, slaveBall);
            
            // 参数校验
            if (masterBall == null || slaveBall == null) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "主球和随球号码不能为空");
            }
            
            // 验证红球号码范围
            if (masterBall < 1 || masterBall > 33) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "主球（红球）号码必须在1-33范围内，错误值：" + masterBall);
            }
            
            // 验证蓝球号码范围
            if (slaveBall < 1 || slaveBall > 16) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "随球（蓝球）号码必须在1-16范围内，错误值：" + slaveBall);
            }
            
            // 查询T8表获取面系数
            T8 t8Record = t8Service.lambdaQuery()
                    .eq(T8::getMasterBallNumber, masterBall)
                    .eq(T8::getSlaveBallNumber, slaveBall)
                    .one();
            
            if (t8Record == null) {
                log.warn("未找到主球（红球）{}和随球（蓝球）{}的组合记录", masterBall, slaveBall);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, 
                        String.format("未找到主球（红球）%d和随球（蓝球）%d的组合记录", masterBall, slaveBall));
            }
            
            Double faceCoefficient = t8Record.getFaceCoefficient();
            
            // 查询主球（红球）与所有蓝球的组合系数
            List<T8> allCombinations = t8Service.lambdaQuery()
                    .eq(T8::getMasterBallNumber, masterBall)
                    .list();

            if (allCombinations.isEmpty()) {
                log.warn("未找到主球（红球）{}的组合记录", masterBall);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR,
                        String.format("未找到主球（红球）%d的组合记录", masterBall));
            }

            // 找出系数最高的球号
            T8 highest = allCombinations.stream()
                    .max(Comparator.comparing(T8::getFaceCoefficient))
                    .orElse(null);

            // 找出系数最低的球号
            T8 lowest = allCombinations.stream()
                    .min(Comparator.comparing(T8::getFaceCoefficient))
                    .orElse(null);

            // 计算平均系数
            double avgCoefficient = allCombinations.stream()
                    .mapToDouble(T8::getFaceCoefficient)
                    .average()
                    .orElse(0.0);

            // 获取最新的一期开奖期号
            Long latestDrawId = lotteryDrawsService.lambdaQuery()
                    .orderByDesc(LotteryDraws::getDrawId)
                    .last("LIMIT 1")
                    .oneOpt()
                    .map(LotteryDraws::getDrawId)
                    .orElse(null);

            // 构建返回结果
            BallCombinationAnalysisVO result = BallCombinationAnalysisVO.builder()
                    .faceCoefficient(faceCoefficient)
                    .highestBall(highest != null ? highest.getSlaveBallNumber() : null)
                    .highestCoefficient(highest != null ? highest.getFaceCoefficient() : null)
                    .lowestBall(lowest != null ? lowest.getSlaveBallNumber() : null)
                    .lowestCoefficient(lowest != null ? lowest.getFaceCoefficient() : null)
                    .averageCoefficient(avgCoefficient)
                    .latestDrawId(latestDrawId)
                    .build();

            log.info("红球与蓝球的组合性分析完成：{}", result);
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("红球与蓝球的组合性分析失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "红球与蓝球的组合性分析失败：" + e.getMessage());
        }
    }

    /**
     * 蓝球与红球的组合性分析
     * @param masterBall 主球号码（蓝球）
     * @param slaveBall 随球号码（红球）
     * @return 面系数分析结果
     */
    @GetMapping("/blue-red-combination-analysis")
    @Operation(summary = "蓝球与红球的组合性分析", description = "根据蓝球主球和红球随球号码，查询t11表获取面系数，并返回扩展分析")
    public ApiResponse<BallCombinationAnalysisVO> blueRedCombinationAnalysis(
            @Parameter(description = "主球号码（蓝球），例如：8", required = true)
            @RequestParam Integer masterBall,
            
            @Parameter(description = "随球号码（红球），例如：5", required = true)
            @RequestParam Integer slaveBall,
            
            HttpServletRequest request) {
        
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到蓝球与红球的组合性分析请求：主球（蓝球）={}，随球（红球）={}", masterBall, slaveBall);
            
            // 参数校验
            if (masterBall == null || slaveBall == null) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "主球和随球号码不能为空");
            }
            
            // 验证蓝球号码范围
            if (masterBall < 1 || masterBall > 16) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "主球（蓝球）号码必须在1-16范围内，错误值：" + masterBall);
            }
            
            // 验证红球号码范围
            if (slaveBall < 1 || slaveBall > 33) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "随球（红球）号码必须在1-33范围内，错误值：" + slaveBall);
            }
            
            // 查询T11表获取面系数
            T11 t11Record = t11Service.lambdaQuery()
                    .eq(T11::getMasterBallNumber, masterBall)
                    .eq(T11::getSlaveBallNumber, slaveBall)
                    .one();
            
            if (t11Record == null) {
                log.warn("未找到主球（蓝球）{}和随球（红球）{}的组合记录", masterBall, slaveBall);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, 
                        String.format("未找到主球（蓝球）%d和随球（红球）%d的组合记录", masterBall, slaveBall));
            }
            
            Double faceCoefficient = t11Record.getFaceCoefficient();
            
            // 查询主球（蓝球）与所有红球的组合系数
            List<T11> allCombinations = t11Service.lambdaQuery()
                    .eq(T11::getMasterBallNumber, masterBall)
                    .list();

            if (allCombinations.isEmpty()) {
                log.warn("未找到主球（蓝球）{}的组合记录", masterBall);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR,
                        String.format("未找到主球（蓝球）%d的组合记录", masterBall));
            }

            // 找出系数最高的球号
            T11 highest = allCombinations.stream()
                    .max(Comparator.comparing(T11::getFaceCoefficient))
                    .orElse(null);

            // 找出系数最低的球号
            T11 lowest = allCombinations.stream()
                    .min(Comparator.comparing(T11::getFaceCoefficient))
                    .orElse(null);

            // 计算平均系数
            double avgCoefficient = allCombinations.stream()
                    .mapToDouble(T11::getFaceCoefficient)
                    .average()
                    .orElse(0.0);

            // 获取最新的一期开奖期号
            Long latestDrawId = lotteryDrawsService.lambdaQuery()
                    .orderByDesc(LotteryDraws::getDrawId)
                    .last("LIMIT 1")
                    .oneOpt()
                    .map(LotteryDraws::getDrawId)
                    .orElse(null);

            // 构建返回结果
            BallCombinationAnalysisVO result = BallCombinationAnalysisVO.builder()
                    .faceCoefficient(faceCoefficient)
                    .highestBall(highest != null ? highest.getSlaveBallNumber() : null)
                    .highestCoefficient(highest != null ? highest.getFaceCoefficient() : null)
                    .lowestBall(lowest != null ? lowest.getSlaveBallNumber() : null)
                    .lowestCoefficient(lowest != null ? lowest.getFaceCoefficient() : null)
                    .averageCoefficient(avgCoefficient)
                    .latestDrawId(latestDrawId)
                    .build();

            log.info("蓝球与红球的组合性分析完成：{}", result);
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("蓝球与红球的组合性分析失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "蓝球与红球的组合性分析失败：" + e.getMessage());
        }
    }

    /**
     * 红球与红球的持续性分析
     * @param masterBall 主球号码（红球）
     * @param slaveBall 随球号码（红球）
     * @return 线系数分析结果
     */
    @GetMapping("/red-red-persistence-analysis")
    @Operation(summary = "红球与红球的持续性分析", description = "根据红球主球和红球随球号码，查询t3表获取线系数，并返回扩展分析")
    public ApiResponse<BallPersistenceAnalysisVO> redRedPersistenceAnalysis(
            @Parameter(description = "主球号码（红球），例如：5", required = true)
            @RequestParam Integer masterBall,
            
            @Parameter(description = "随球号码（红球），例如：12", required = true)
            @RequestParam Integer slaveBall,
            
            HttpServletRequest request) {
        
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到红球与红球的持续性分析请求：主球（红球）={}，随球（红球）={}", masterBall, slaveBall);
            
            // 参数校验
            if (masterBall == null || slaveBall == null) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "主球和随球号码不能为空");
            }
            
            // 验证红球号码范围
            if (masterBall < 1 || masterBall > 33) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "主球（红球）号码必须在1-33范围内，错误值：" + masterBall);
            }
            
            if (slaveBall < 1 || slaveBall > 33) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "随球（红球）号码必须在1-33范围内，错误值：" + slaveBall);
            }
            
            // 查询T3表获取线系数
            T3 t3Record = t3Service.lambdaQuery()
                    .eq(T3::getMasterBallNumber, masterBall)
                    .eq(T3::getSlaveBallNumber, slaveBall)
                    .one();
            
            if (t3Record == null) {
                log.warn("未找到主球（红球）{}和随球（红球）{}的持续性记录", masterBall, slaveBall);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, 
                        String.format("未找到主球（红球）%d和随球（红球）%d的持续性记录", masterBall, slaveBall));
            }
            
            Double lineCoefficient = t3Record.getLineCoefficient();
            
            // 查询主球与其他所有红球的持续性系数
            List<T3> allCombinations = t3Service.lambdaQuery()
                    .eq(T3::getMasterBallNumber, masterBall)
                    .list();

            if (allCombinations.isEmpty()) {
                log.warn("未找到主球（红球）{}的持续性记录", masterBall);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR,
                        String.format("未找到主球（红球）%d的持续性记录", masterBall));
            }

            // 找出系数最高的球号
            T3 highest = allCombinations.stream()
                    .max(Comparator.comparing(T3::getLineCoefficient))
                    .orElse(null);

            // 找出系数最低的球号
            T3 lowest = allCombinations.stream()
                    .min(Comparator.comparing(T3::getLineCoefficient))
                    .orElse(null);

            // 计算平均系数
            double avgCoefficient = allCombinations.stream()
                    .mapToDouble(T3::getLineCoefficient)
                    .average()
                    .orElse(0.0);

            // 获取最新的一期开奖期号
            Long latestDrawId = lotteryDrawsService.lambdaQuery()
                    .orderByDesc(LotteryDraws::getDrawId)
                    .last("LIMIT 1")
                    .oneOpt()
                    .map(LotteryDraws::getDrawId)
                    .orElse(null);
            
            // 构建返回结果
            BallPersistenceAnalysisVO result = BallPersistenceAnalysisVO.builder()
                    .lineCoefficient(lineCoefficient)
                    .highestBall(highest != null ? highest.getSlaveBallNumber() : null)
                    .highestCoefficient(highest != null ? highest.getLineCoefficient() : null)
                    .lowestBall(lowest != null ? lowest.getSlaveBallNumber() : null)
                    .lowestCoefficient(lowest != null ? lowest.getLineCoefficient() : null)
                    .averageCoefficient(avgCoefficient)
                    .latestDrawId(latestDrawId)
                    .build();

            log.info("红球与红球的持续性分析完成：{}", result);
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("红球与红球的持续性分析失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "红球与红球的持续性分析失败：" + e.getMessage());
        }
    }

    /**
     * 蓝球与蓝球的持续性分析
     * @param masterBall 主球号码（蓝球）
     * @param slaveBall 随球号码（蓝球）
     * @return 线系数分析结果
     */
    @GetMapping("/blue-blue-persistence-analysis")
    @Operation(summary = "蓝球与蓝球的持续性分析", description = "根据蓝球主球和蓝球随球号码，查询t5表获取线系数，并返回扩展分析")
    public ApiResponse<BallPersistenceAnalysisVO> blueBluePersistenceAnalysis(
            @Parameter(description = "主球号码（蓝球），例如：8", required = true)
            @RequestParam Integer masterBall,
            
            @Parameter(description = "随球号码（蓝球），例如：12", required = true)
            @RequestParam Integer slaveBall,
            
            HttpServletRequest request) {
        
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到蓝球与蓝球的持续性分析请求：主球（蓝球）={}，随球（蓝球）={}", masterBall, slaveBall);
            
            // 参数校验
            if (masterBall == null || slaveBall == null) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "主球和随球号码不能为空");
            }
            
            // 验证蓝球号码范围
            if (masterBall < 1 || masterBall > 16) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "主球（蓝球）号码必须在1-16范围内，错误值：" + masterBall);
            }
            
            if (slaveBall < 1 || slaveBall > 16) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "随球（蓝球）号码必须在1-16范围内，错误值：" + slaveBall);
            }
            
            // 查询T5表获取线系数
            T5 t5Record = t5Service.lambdaQuery()
                    .eq(T5::getMasterBallNumber, masterBall)
                    .eq(T5::getSlaveBallNumber, slaveBall)
                    .one();
            
            if (t5Record == null) {
                log.warn("未找到主球（蓝球）{}和随球（蓝球）{}的持续性记录", masterBall, slaveBall);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, 
                        String.format("未找到主球（蓝球）%d和随球（蓝球）%d的持续性记录", masterBall, slaveBall));
            }
            
            Double lineCoefficient = t5Record.getLineCoefficient();
            
            // 查询主球与其他所有蓝球的持续性系数
            List<T5> allCombinations = t5Service.lambdaQuery()
                    .eq(T5::getMasterBallNumber, masterBall)
                    .list();

            if (allCombinations.isEmpty()) {
                log.warn("未找到主球（蓝球）{}的持续性记录", masterBall);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR,
                        String.format("未找到主球（蓝球）%d的持续性记录", masterBall));
            }

            // 找出系数最高的球号
            T5 highest = allCombinations.stream()
                    .max(Comparator.comparing(T5::getLineCoefficient))
                    .orElse(null);

            // 找出系数最低的球号
            T5 lowest = allCombinations.stream()
                    .min(Comparator.comparing(T5::getLineCoefficient))
                    .orElse(null);

            // 计算平均系数
            double avgCoefficient = allCombinations.stream()
                    .mapToDouble(T5::getLineCoefficient)
                    .average()
                    .orElse(0.0);

            // 获取最新的一期开奖期号
            Long latestDrawId = lotteryDrawsService.lambdaQuery()
                    .orderByDesc(LotteryDraws::getDrawId)
                    .last("LIMIT 1")
                    .oneOpt()
                    .map(LotteryDraws::getDrawId)
                    .orElse(null);

            // 构建返回结果
            BallPersistenceAnalysisVO result = BallPersistenceAnalysisVO.builder()
                    .lineCoefficient(lineCoefficient)
                    .highestBall(highest != null ? highest.getSlaveBallNumber() : null)
                    .highestCoefficient(highest != null ? highest.getLineCoefficient() : null)
                    .lowestBall(lowest != null ? lowest.getSlaveBallNumber() : null)
                    .lowestCoefficient(lowest != null ? lowest.getLineCoefficient() : null)
                    .averageCoefficient(avgCoefficient)
                    .latestDrawId(latestDrawId)
                    .build();
            
            log.info("蓝球与蓝球的持续性分析完成：{}", result);
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("蓝球与蓝球的持续性分析失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "蓝球与蓝球的持续性分析失败：" + e.getMessage());
        }
    }

    /**
     * 红球与蓝球的持续性分析
     * @param masterBall 主球号码（红球）
     * @param slaveBall 随球号码（蓝球）
     * @return 线系数分析结果
     */
    @GetMapping("/red-blue-persistence-analysis")
    @Operation(summary = "红球与蓝球的持续性分析", description = "根据红球主球和蓝球随球号码，查询t6表获取线系数，并返回扩展分析")
    public ApiResponse<BallPersistenceAnalysisVO> redBluePersistenceAnalysis(
            @Parameter(description = "主球号码（红球），例如：5", required = true)
            @RequestParam Integer masterBall,
            
            @Parameter(description = "随球号码（蓝球），例如：8", required = true)
            @RequestParam Integer slaveBall,
            
            HttpServletRequest request) {
        
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到红球与蓝球的持续性分析请求：主球（红球）={}，随球（蓝球）={}", masterBall, slaveBall);
            
            // 参数校验
            if (masterBall == null || slaveBall == null) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "主球和随球号码不能为空");
            }
            
            // 验证红球号码范围
            if (masterBall < 1 || masterBall > 33) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "主球（红球）号码必须在1-33范围内，错误值：" + masterBall);
            }
            
            // 验证蓝球号码范围
            if (slaveBall < 1 || slaveBall > 16) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "随球（蓝球）号码必须在1-16范围内，错误值：" + slaveBall);
            }
            
            // 查询T6表获取线系数
            T6 t6Record = t6Service.lambdaQuery()
                    .eq(T6::getMasterBallNumber, masterBall)
                    .eq(T6::getSlaveBallNumber, slaveBall)
                    .one();
            
            if (t6Record == null) {
                log.warn("未找到主球（红球）{}和随球（蓝球）{}的持续性记录", masterBall, slaveBall);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, 
                        String.format("未找到主球（红球）%d和随球（蓝球）%d的持续性记录", masterBall, slaveBall));
            }
            
            Double lineCoefficient = t6Record.getLineCoefficient();
            
            // 查询主球（红球）与所有蓝球的持续性系数
            List<T6> allCombinations = t6Service.lambdaQuery()
                    .eq(T6::getMasterBallNumber, masterBall)
                    .list();

            if (allCombinations.isEmpty()) {
                log.warn("未找到主球（红球）{}的持续性记录", masterBall);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR,
                        String.format("未找到主球（红球）%d的持续性记录", masterBall));
            }

            // 找出系数最高的球号
            T6 highest = allCombinations.stream()
                    .max(Comparator.comparing(T6::getLineCoefficient))
                    .orElse(null);

            // 找出系数最低的球号
            T6 lowest = allCombinations.stream()
                    .min(Comparator.comparing(T6::getLineCoefficient))
                    .orElse(null);

            // 计算平均系数
            double avgCoefficient = allCombinations.stream()
                    .mapToDouble(T6::getLineCoefficient)
                    .average()
                    .orElse(0.0);

            // 获取最新的一期开奖期号
            Long latestDrawId = lotteryDrawsService.lambdaQuery()
                    .orderByDesc(LotteryDraws::getDrawId)
                    .last("LIMIT 1")
                    .oneOpt()
                    .map(LotteryDraws::getDrawId)
                    .orElse(null);

            // 构建返回结果
            BallPersistenceAnalysisVO result = BallPersistenceAnalysisVO.builder()
                    .lineCoefficient(lineCoefficient)
                    .highestBall(highest != null ? highest.getSlaveBallNumber() : null)
                    .highestCoefficient(highest != null ? highest.getLineCoefficient() : null)
                    .lowestBall(lowest != null ? lowest.getSlaveBallNumber() : null)
                    .lowestCoefficient(lowest != null ? lowest.getLineCoefficient() : null)
                    .averageCoefficient(avgCoefficient)
                    .latestDrawId(latestDrawId)
                    .build();
            
            log.info("红球与蓝球的持续性分析完成：{}", result);
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("红球与蓝球的持续性分析失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "红球与蓝球的持续性分析失败：" + e.getMessage());
        }
    }

    /**
     * 蓝球与红球的持续性分析
     * @param masterBall 主球号码（蓝球）
     * @param slaveBall 随球号码（红球）
     * @return 线系数分析结果
     */
    @GetMapping("/blue-red-persistence-analysis")
    @Operation(summary = "蓝球与红球的持续性分析", description = "根据蓝球主球和红球随球号码，查询t4表获取线系数，并返回扩展分析")
    public ApiResponse<BallPersistenceAnalysisVO> blueRedPersistenceAnalysis(
            @Parameter(description = "主球号码（蓝球），例如：8", required = true)
            @RequestParam Integer masterBall,
            
            @Parameter(description = "随球号码（红球），例如：5", required = true)
            @RequestParam Integer slaveBall,
            
            HttpServletRequest request) {
        
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        Date now = new Date();
        if (loginUser.getVipExpire() == null || loginUser.getVipExpire().before(now)) {
            return ResultUtils.error(ErrorCode.NO_AUTH_ERROR, "VIP会员已过期，请续费后使用");
        }
        try {
            log.info("接收到蓝球与红球的持续性分析请求：主球（蓝球）={}，随球（红球）={}", masterBall, slaveBall);
            
            // 参数校验
            if (masterBall == null || slaveBall == null) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "主球和随球号码不能为空");
            }
            
            // 验证蓝球号码范围
            if (masterBall < 1 || masterBall > 16) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "主球（蓝球）号码必须在1-16范围内，错误值：" + masterBall);
            }
            
            // 验证红球号码范围
            if (slaveBall < 1 || slaveBall > 33) {
                return ResultUtils.error(ErrorCode.PARAMS_ERROR, "随球（红球）号码必须在1-33范围内，错误值：" + slaveBall);
            }
            
            // 查询T4表获取线系数
            T4 t4Record = t4Service.lambdaQuery()
                    .eq(T4::getMasterBallNumber, masterBall)
                    .eq(T4::getSlaveBallNumber, slaveBall)
                    .one();
            
            if (t4Record == null) {
                log.warn("未找到主球（蓝球）{}和随球（红球）{}的持续性记录", masterBall, slaveBall);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, 
                        String.format("未找到主球（蓝球）%d和随球（红球）%d的持续性记录", masterBall, slaveBall));
            }
            
            Double lineCoefficient = t4Record.getLineCoefficient();
            
            // 查询主球（蓝球）与所有红球的持续性系数
            List<T4> allCombinations = t4Service.lambdaQuery()
                    .eq(T4::getMasterBallNumber, masterBall)
                    .list();

            if (allCombinations.isEmpty()) {
                log.warn("未找到主球（蓝球）{}的持续性记录", masterBall);
                return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR,
                        String.format("未找到主球（蓝球）%d的持续性记录", masterBall));
            }

            // 找出系数最高的球号
            T4 highest = allCombinations.stream()
                    .max(Comparator.comparing(T4::getLineCoefficient))
                    .orElse(null);

            // 找出系数最低的球号
            T4 lowest = allCombinations.stream()
                    .min(Comparator.comparing(T4::getLineCoefficient))
                    .orElse(null);

            // 计算平均系数
            double avgCoefficient = allCombinations.stream()
                    .mapToDouble(T4::getLineCoefficient)
                    .average()
                    .orElse(0.0);

            // 获取最新的一期开奖期号
            Long latestDrawId = lotteryDrawsService.lambdaQuery()
                    .orderByDesc(LotteryDraws::getDrawId)
                    .last("LIMIT 1")
                    .oneOpt()
                    .map(LotteryDraws::getDrawId)
                    .orElse(null);

            // 构建返回结果
            BallPersistenceAnalysisVO result = BallPersistenceAnalysisVO.builder()
                    .lineCoefficient(lineCoefficient)
                    .highestBall(highest != null ? highest.getSlaveBallNumber() : null)
                    .highestCoefficient(highest != null ? highest.getLineCoefficient() : null)
                    .lowestBall(lowest != null ? lowest.getSlaveBallNumber() : null)
                    .lowestCoefficient(lowest != null ? lowest.getLineCoefficient() : null)
                    .averageCoefficient(avgCoefficient)
                    .latestDrawId(latestDrawId)
                    .build();
            
            log.info("蓝球与红球的持续性分析完成：{}", result);
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("蓝球与红球的持续性分析失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "蓝球与红球的持续性分析失败：" + e.getMessage());
        }
    }

    /**
     * 获取首球命中率统计
     * @return 首球命中次数和命中率统计
     */
    @GetMapping("/first-ball-hit-rate")
    @Operation(summary = "获取首球命中率统计", description = "统计用户的首球命中次数和命中率")
    public ApiResponse<BallHitRateVO> getFirstBallHitRate(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        try {
            log.info("接收到获取首球命中率统计请求");
            
            // 调用服务获取首球命中率
            BallHitRateVO result = ballAnalysisService.getFirstBallHitRate(loginUser.getId());
            
            log.info("获取首球命中率统计完成，命中次数：{}，总次数：{}，命中率：{}", 
                     result.getHitCount(), result.getTotalCount(), result.getHitRate());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取首球命中率统计失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取首球命中率统计失败：" + e.getMessage());
        }
    }

    /**
     * 获取蓝球命中率统计
     * @return 蓝球命中次数和命中率统计
     */
    @GetMapping("/blue-ball-hit-rate")
    @Operation(summary = "获取蓝球命中率统计", description = "统计用户的蓝球命中次数和命中率")
    public ApiResponse<BallHitRateVO> getBlueBallHitRate(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        try {
            log.info("接收到获取蓝球命中率统计请求");
            
            // 调用服务获取蓝球命中率
            BallHitRateVO result = ballAnalysisService.getBlueBallHitRate(loginUser.getId());
            
            log.info("获取蓝球命中率统计完成，命中次数：{}，总次数：{}，命中率：{}", 
                     result.getHitCount(), result.getTotalCount(), result.getHitRate());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取蓝球命中率统计失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取蓝球命中率统计失败：" + e.getMessage());
        }
    }


    
    /**
     * 奖金统计
     * @return 奖金统计信息（各中奖等级、中奖次数、单奖金额、奖金合计）
     */
    @GetMapping("/prize-statistics")
    @Operation(summary = "奖金统计", description = "统计用户所有中奖记录，按等级汇总各等级的中奖次数和奖金")
    public ApiResponse<PrizeEstimateVO> getPrizeStatistics(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        try {
            log.info("接收到奖金统计请求");
            
            // 调用服务进行奖金统计
            PrizeEstimateVO result = ballAnalysisService.getPrizeStatistics(loginUser.getId(), null);
            
            log.info("奖金统计完成，总奖金：{}", result.getTotalPrize());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("奖金统计失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "奖金统计失败：" + e.getMessage());
        }
    }

    /**
     * 获取近10期开奖期号
     * @return 近10期开奖期号列表
     */
    @GetMapping("/recent-10-draw-ids")
    @Operation(summary = "获取近10期开奖期号", description = "获取lottery_draws表中最新的10期开奖期号，按开奖期号倒序排列")
    public ApiResponse<List<Long>> getRecent10DrawIds(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        try {
            log.info("接收到获取近10期开奖期号请求");
            
            // 查询最近10期开奖期号
            List<Long> drawIds = lotteryDrawsService.lambdaQuery()
                    .select(LotteryDraws::getDrawId)
                    .orderByDesc(LotteryDraws::getDrawId)
                    .last("LIMIT 10")
                    .list()
                    .stream()
                    .map(LotteryDraws::getDrawId)
                    .collect(java.util.stream.Collectors.toList());
            
            log.info("获取近10期开奖期号完成，返回{}条记录", drawIds.size());
            return ResultUtils.success(drawIds);
            
        } catch (Exception e) {
            log.error("获取近10期开奖期号失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取近10期开奖期号失败：" + e.getMessage());
        }
    }

    /**
     * 获取红球命中率统计
     * @return 红球命中总数和命中率
     */
    @GetMapping("/red-ball-hit-rate")
    @Operation(summary = "获取红球命中率统计", description = "统计用户的总红球命中次数和命中率")
    public ApiResponse<RedBallHitRateVO> getRedBallHitRate(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "您还未登录，请登录后查看");
        }
        try {
            log.info("接收到获取红球命中率统计请求");
            
            // 调用服务获取红球命中率
            RedBallHitRateVO result = ballAnalysisService.getRedBallHitRate(loginUser.getId());
            
            log.info("获取红球命中率统计完成，命中总数：{}，预测总数：{}，命中率：{}", 
                     result.getTotalHitCount(), result.getTotalPredictedCount(), result.getHitRate());
            return ResultUtils.success(result);
            
        } catch (Exception e) {
            log.error("获取红球命中率统计失败：{}", e.getMessage(), e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取红球命中率统计失败：" + e.getMessage());
        }
    }

} 